using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Reflection;
using System.Text;

namespace ClownFish
{
	public sealed class CPQuery
	{
		private enum SPStep
		{
			const_0,
			const_1,
			const_2
		}

		private int int_0;

		private StringBuilder stringBuilder_0 = new StringBuilder(1024);

		private List<KeyValuePair<string, QueryParameter>> list_0 = new List<KeyValuePair<string, QueryParameter>>(10);

		private Func<string, string> func_0 = new Func<string, string>(CPQuery.smethod_0);

		private Func<string, string> func_1 = new Func<string, string>(CPQuery.smethod_0);

		private bool bool_0;

		private CPQuery.SPStep spstep_0;

		public CPQuery(string text, bool autoDiscoverParameters)
		{
			this.bool_0 = autoDiscoverParameters;
			this.method_0(text);
		}

		public CPQuery SetEvalNameDelegate(Func<string, string> placeholderDelegate, Func<string, string> paraNameDelegate)
		{
			if (placeholderDelegate != null)
			{
				this.func_0 = placeholderDelegate;
			}
			if (paraNameDelegate != null)
			{
				this.func_1 = paraNameDelegate;
			}
			return this;
		}

		private static string smethod_0(string string_0)
		{
			return "@" + string_0;
		}

		public override string ToString()
		{
			return this.stringBuilder_0.ToString();
		}

		public void BindToCommand(DbCommand command)
		{
			if (command == null)
			{
				throw new ArgumentNullException("command");
			}
			command.CommandText = this.stringBuilder_0.ToString();
			command.Parameters.Clear();
			foreach (KeyValuePair<string, QueryParameter> current in this.list_0)
			{
				DbParameter dbParameter = command.CreateParameter();
				dbParameter.ParameterName = current.Key;
				dbParameter.Value = current.Value.Value;
				command.Parameters.Add(dbParameter);
			}
		}

		public static CPQuery New()
		{
			return new CPQuery(null, false);
		}

		public static CPQuery New(bool autoDiscoverParameters)
		{
			return new CPQuery(null, autoDiscoverParameters);
		}

		private void method_0(string string_0)
		{
			if (string.IsNullOrEmpty(string_0))
			{
				return;
			}
			if (!this.bool_0)
			{
				this.stringBuilder_0.Append(string_0);
				return;
			}
			if (this.spstep_0 == CPQuery.SPStep.const_0)
			{
				if (string_0[string_0.Length - 1] == '\'')
				{
					this.stringBuilder_0.Append(string_0.Substring(0, string_0.Length - 1));
					this.spstep_0 = CPQuery.SPStep.const_1;
					return;
				}
				object obj = this.method_3(string_0);
				if (obj == null)
				{
					this.stringBuilder_0.Append(string_0);
					return;
				}
				this.method_1(obj.AsQueryParameter());
				return;
			}
			else
			{
				if (this.spstep_0 == CPQuery.SPStep.const_1)
				{
					this.method_1(string_0.AsQueryParameter());
					return;
				}
				if (string_0[0] != '\'')
				{
					throw new ArgumentException("正在等待以单引号开始的字符串，但参数不符合预期格式。");
				}
				this.stringBuilder_0.Append(string_0.Substring(1));
				this.spstep_0 = CPQuery.SPStep.const_0;
				return;
			}
		}

		private void method_1(QueryParameter queryParameter_0)
		{
			if (this.bool_0 && this.spstep_0 == CPQuery.SPStep.const_2)
			{
				throw new InvalidOperationException("正在等待以单引号开始的字符串，此时不允许再拼接其它参数。");
			}
			string arg = "p" + this.int_0++.ToString();
			if (this.func_0 == this.func_1)
			{
				string text = this.func_0(arg);
				this.stringBuilder_0.Append(text);
				this.list_0.Add(new KeyValuePair<string, QueryParameter>(text, queryParameter_0));
			}
			else
			{
				this.stringBuilder_0.Append(this.func_0(arg));
				this.list_0.Add(new KeyValuePair<string, QueryParameter>(this.func_1(arg), queryParameter_0));
			}
			if (this.bool_0 && this.spstep_0 == CPQuery.SPStep.const_1)
			{
				this.spstep_0 = CPQuery.SPStep.const_2;
			}
		}

		internal void method_2(string string_0, QueryParameter queryParameter_0)
		{
			if (string.IsNullOrEmpty(string_0))
			{
				string_0 = this.func_1("p" + this.int_0++.ToString());
			}
			this.list_0.Add(new KeyValuePair<string, QueryParameter>(string_0, queryParameter_0));
		}

		private object method_3(string string_0)
		{
			int num = 0;
			if (int.TryParse(string_0, out num))
			{
				return num;
			}
			DateTime minValue = DateTime.MinValue;
			if (DateTime.TryParse(string_0, out minValue))
			{
				return minValue;
			}
			decimal num2 = 0m;
			if (decimal.TryParse(string_0, out num2))
			{
				return num2;
			}
			return null;
		}

		public static CPQuery operator +(CPQuery query, string string_0)
		{
			query.method_0(string_0);
			return query;
		}

		public static CPQuery operator +(CPQuery query, QueryParameter queryParameter_0)
		{
			query.method_1(queryParameter_0);
			return query;
		}

		public static CPQuery Format(string format, params object[] parameters)
		{
			return CPQuery.New().AppendFormat(format, parameters);
		}

		public CPQuery AppendFormat(string format, params object[] parameters)
		{
			if (string.IsNullOrEmpty(format))
			{
				throw new ArgumentNullException("format");
			}
			if (parameters != null && parameters.Length != 0)
			{
				object[] array = new object[parameters.Length];
				for (int i = 0; i < parameters.Length; i++)
				{
					array[i] = this.func_0("p" + i.ToString());
				}
				this.stringBuilder_0.Append(string.Format(format, array));
				for (int j = 0; j < parameters.Length; j++)
				{
					string string_ = this.func_1("p" + j.ToString());
					this.method_2(string_, new QueryParameter(parameters[j]));
				}
				return this;
			}
			this.stringBuilder_0.Append(format);
			return this;
		}

		public static CPQuery From(string parameterizedSQL, object argsObject)
		{
			return CPQuery.New().AppendFrom(parameterizedSQL, argsObject);
		}

		public CPQuery AppendFrom(string parameterizedSQL, object argsObject)
		{
			if (string.IsNullOrEmpty(parameterizedSQL))
			{
				throw new ArgumentNullException("parameterizedSQL");
			}
			this.stringBuilder_0.Append(parameterizedSQL);
			if (argsObject != null)
			{
				PropertyInfo[] properties = argsObject.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
				PropertyInfo[] array = properties;
				for (int i = 0; i < array.Length; i++)
				{
					PropertyInfo propertyInfo = array[i];
					QueryParameter queryParameter_ = new QueryParameter(propertyInfo.smethod_0(argsObject));
					this.method_2(this.func_1(propertyInfo.Name), queryParameter_);
				}
			}
			return this;
		}
	}
}
